#include "VSShaderMainFunction.h"
#include "VSShaderStringFactory.h"
#include "VSGraphicInclude.h"
#include "VSLight.h"
using namespace VSEngine2;
IMPLEMENT_RTTI_NoCreateFun(VSShaderMainFunction,VSShaderFunction)
IMPLEMENT_INITIAL_NO_CLASS_FACTORY_BEGIN(VSShaderMainFunction)
IMPLEMENT_INITIAL_NO_CLASS_FACTORY_END
BEGIN_ADD_PROPERTY(VSShaderMainFunction,VSShaderFunction)
REGISTER_PROPERTY(m_uiVESRGBWrite,VESRGBWrite,VSProperty::F_SAVE_LOAD_CLONE)
REGISTER_ENUM_PROPERTY(m_uiSpecularType,ShaderMainFunctionSpecularType,SpecularType,VSProperty::F_SAVE_LOAD_CLONE)
REGISTER_PROPERTY(m_uiPassId,PassId,VSProperty::F_SAVE_LOAD_CLONE)
REGISTER_PROPERTY(m_RenderState,RenderState,VSProperty::F_SAVE_LOAD_CLONE)
BEGIN_ADD_ENUM
ADD_ENUM(ShaderMainFunctionSpecularType,ST_BlinnPhong)
ADD_ENUM(ShaderMainFunctionSpecularType,ST_Phong)
END_ADD_ENUM
END_ADD_PROPERTY


VSShaderMainFunction::VSShaderMainFunction(const VSUsedName &ShowName,VSMaterial * pMaterial)
					:VSShaderFunction(ShowName,pMaterial)
{
	

	m_LightArray.Clear();
	m_uiVESRGBWrite = false;
	m_uiSpecularType = ST_BlinnPhong;
	m_uiPassId = 0;
	VSString InputName = _T("DiffuseColor");
	VSInputNode * pInputNode = NULL;

	pInputNode = VS_NEW VSInputNode(VSPutNode::VT_4,InputName,this);
	VSMAC_ASSERT(pInputNode);
	m_pInput.AddElement(pInputNode);

	InputName = _T("EmissiveColor");
	pInputNode = NULL;
	pInputNode = VS_NEW VSInputNode(VSPutNode::VT_4,InputName,this);
	VSMAC_ASSERT(pInputNode);
	m_pInput.AddElement(pInputNode);

	InputName = _T("SpecularColor");
	pInputNode = NULL;
	pInputNode = VS_NEW VSInputNode(VSPutNode::VT_4,InputName,this);
	VSMAC_ASSERT(pInputNode);
	m_pInput.AddElement(pInputNode);

	InputName = _T("SpecularPow");
	pInputNode = NULL;
	pInputNode = VS_NEW VSInputNode(VSPutNode::VT_1,InputName,this);
	VSMAC_ASSERT(pInputNode);
	m_pInput.AddElement(pInputNode);

	InputName = _T("Normal");
	pInputNode = NULL;
	pInputNode = VS_NEW VSInputNode(VSPutNode::VT_4,InputName,this);
	VSMAC_ASSERT(pInputNode);
	m_pInput.AddElement(pInputNode);


	InputName = _T("Alpha");
	pInputNode = NULL;
	pInputNode = VS_NEW VSInputNode(VSPutNode::VT_1,InputName,this);
	VSMAC_ASSERT(pInputNode);
	m_pInput.AddElement(pInputNode);

	VSString OutputName = _T("OutputColor");
	VSOutputNode * pOutputNode = NULL;
	pOutputNode = VS_NEW VSOutputNode(VSPutNode::VT_4,OutputName,this);
	VSMAC_ASSERT(pOutputNode);
	m_pOutput.AddElement(pOutputNode);
}

VSShaderMainFunction::~VSShaderMainFunction()
{

}
VSShaderMainFunction::VSShaderMainFunction()
{
	m_LightArray.Clear();
	m_uiVESRGBWrite = false;
	m_uiSpecularType = ST_BlinnPhong;
	m_uiPassId = 0;
}
bool VSShaderMainFunction::GetShaderTreeString(VSString &OutString,unsigned int uiOutPutStringType)
{
	if(m_bIsVisited == 1)
		return 1;
	else
	{
		m_bIsVisited = 1;
		if (uiOutPutStringType == OST_FINAL)
		{
			for(unsigned int i = 0 ; i < m_pInput.GetNum(); i++)
			{
				if(m_pInput[i]->GetOutputLink() == NULL)
					continue;
				else
				{
					((VSShaderFunction *)m_pInput[i]->GetOutputLink()->GetOwner())->GetShaderTreeString(OutString);

				}

			}
		}
		else if (uiOutPutStringType == OST_NORMAL)
		{
			VSArray<unsigned int> Index;
			Index.AddElement(IN_NORMAL);
			Index.AddElement(IN_ALPHA);
			for(unsigned int i = 0 ; i < Index.GetNum() ; i++)
			{
				if(m_pInput[Index[i]]->GetOutputLink())
				{
					((VSShaderFunction *)m_pInput[Index[i]]->GetOutputLink()->GetOwner())->GetShaderTreeString(OutString);

				}
			}
		}
		GetDelareString(OutString);
		if(!GetInputValueString(OutString,uiOutPutStringType))
			return 0;
		if(!GetOutPutValueString(OutString))
			return 0;
		if (uiOutPutStringType == OST_FINAL)
		{
			if(!GetFuntionString(OutString))
				return 0;
		}
		else if (uiOutPutStringType == OST_NORMAL)
		{
			if (!GetNormalString(OutString))
			{
				return 0;
			}
		}
		return 1;
	}
}
void VSShaderMainFunction::GetDelareString(VSString &OutString)
{
	VSShaderStringFactory::ms_WorldNormal = _T("WorldNormal");
	VSShaderStringFactory::ms_WorldPos = _T("WorldPos");
	VSShaderStringFactory::ms_WorldCameraDir = _T("WorldCameraDir");
	OutString += VSRenderer::ms_pRenderer->Float3() + _T("WorldNormal;\n");
	OutString += VSRenderer::ms_pRenderer->Float3() +  _T("WorldPos;\n");
	OutString += VSRenderer::ms_pRenderer->Float3() + _T("WorldCameraDir;\n");
}
bool VSShaderMainFunction::GetNormalString(VSString &OutString)const
{
	if(VSShaderStringFactory::ms_PSInputLocalNormal.GetLength() == 0)
	{
		OutString += VSShaderStringFactory::ms_WorldNormal + _T(" = ") + VSRenderer::ms_pRenderer->Float3Const(_T("0"),_T("0"),_T("0")) + _T(";\n");
	}
	else if(!m_pInput[IN_NORMAL]->GetOutputLink() || VSShaderStringFactory::ms_PSInputLocalTangent.GetLength() == 0)
	{

		OutString += VSShaderStringFactory::ms_WorldNormal + _T(" = ");
		VSRenderer::ms_pRenderer->LocalToWorldNormal(VSShaderStringFactory::ms_PSInputLocalNormal,OutString);
		OutString += _T(";\n");

	}
	else
	{

		OutString += VSRenderer::ms_pRenderer->Float3() + _T("LocalNormal = ");
		VSRenderer::ms_pRenderer->BumpNormal(m_pInput[IN_NORMAL]->GetNodeName().GetString(),OutString); 
		OutString += _T(";\n");


		OutString += VSShaderStringFactory::ms_WorldNormal + _T(" = ");
		VSRenderer::ms_pRenderer->LocalToWorldNormal(_T("LocalNormal"),OutString);
		OutString += _T(";\n");
	}
	VSString NodeStringRG = VSRenderer::ms_pRenderer->GetValueElement(m_pOutput[OUT_COLOR],VSRenderer::VE_R | VSRenderer::VE_G);
	OutString +=  NodeStringRG + _T(" = ");
	VSRenderer::ms_pRenderer->DecodeNormal3(VSShaderStringFactory::ms_WorldNormal,OutString);
	OutString += _T(";\n");
	VSString NodeStringB = VSRenderer::ms_pRenderer->GetValueElement(m_pOutput[OUT_COLOR],VSRenderer::VE_B);
	OutString += NodeStringB + _T(" = ") + VSShaderStringFactory::ms_PSInputViewZ + _T("/") + VSShaderStringFactory::ms_FarZ;
	OutString += _T(";\n");
	VSString NodeStringA = VSRenderer::ms_pRenderer->GetValueElement(m_pOutput[OUT_COLOR],VSRenderer::VE_A);
	OutString += NodeStringA + _T(" = ") + m_pInput[IN_ALPHA]->GetNodeName().GetString();
	OutString += _T(";\n");
	OutString +=  VSShaderStringFactory::ms_PSTextureOutputColorValue + _T(" = ") + m_pOutput[OUT_COLOR]->GetNodeName().GetString() + _T(";\n");
	return true;
}
bool VSShaderMainFunction::GetInputValueString(VSString &OutString,unsigned int uiOutPutStringType)const
{
	if(!VSRenderer::ms_pRenderer)
		return 0;
	VSString Temp;
	if (uiOutPutStringType == OST_FINAL)
	{
		for(unsigned int i = 0 ; i < m_pInput.GetNum() ; i++)
		{

			if(m_pInput[i]->GetValueType() == VSPutNode::VT_1)
			{
				OutString +=VSRenderer::ms_pRenderer->Float() + _T(" ");/*_T("float ");*/
				if (i == IN_ALPHA)
				{
					Temp = VSRenderer::ms_pRenderer->FloatConst(_T("1"));
				}
				else
				{
					Temp = VSRenderer::ms_pRenderer->FloatConst(_T("0"));
				}
				
			}
			else if(m_pInput[i]->GetValueType() == VSPutNode::VT_2)
			{
				OutString +=VSRenderer::ms_pRenderer->Float2() + _T(" ");/*_T("float2 ");*/
				Temp = VSRenderer::ms_pRenderer->Float2Const(_T("0"),_T("0"));/*_T("float2(0,0)");*/
			}
			else if(m_pInput[i]->GetValueType() == VSPutNode::VT_3)
			{
				OutString +=VSRenderer::ms_pRenderer->Float3() + _T(" ");/*_T("float3 ");*/
				Temp = VSRenderer::ms_pRenderer->Float3Const(_T("0"),_T("0"),_T("0"));/*_T("float3(0,0,0)");*/
			}
			else if(m_pInput[i]->GetValueType() == VSPutNode::VT_4)
			{
				OutString +=VSRenderer::ms_pRenderer->Float4() + _T(" ");/*_T("float4 ");*/
				Temp = VSRenderer::ms_pRenderer->Float4Const(_T("0"),_T("0"),_T("0"),_T("1"));/*_T("float4(0,0,0,1)");*/
			}
			else
				return 0;
			if(!m_pInput[i]->GetOutputLink())
			{
				OutString += m_pInput[i]->GetNodeName().GetString() + _T(" = ") + Temp + _T(";\n");
				continue;
			}
			// 		if(m_pInput[i]->GetValueType() != m_pInput[i]->GetOutputLink()->GetValueType())
			// 			return 0;
			OutString += GetValueEqualString(m_pInput[i]->GetOutputLink(),m_pInput[i]);/*m_pInput[i]->GetNodeName() + _T(" = ") + m_pInput[i]->GetOutputLink()->GetNodeName() + _T(";\n");*/
		}
	}
	else if(uiOutPutStringType == OST_NORMAL)
	{

		VSArray<unsigned int> Index;
		Index.AddElement(IN_NORMAL);
		Index.AddElement(IN_ALPHA);
		
		for(unsigned int i = 0 ; i < Index.GetNum() ; i++)
		{

			if(m_pInput[Index[i]]->GetValueType() == VSPutNode::VT_1)
			{
				OutString +=VSRenderer::ms_pRenderer->Float() + _T(" ");/*_T("float ");*/
				if (Index[i] == IN_ALPHA)
				{
					Temp = VSRenderer::ms_pRenderer->FloatConst(_T("1"));
				}
				else
				{
					Temp = VSRenderer::ms_pRenderer->FloatConst(_T("0"));
				}

			}
			else if(m_pInput[Index[i]]->GetValueType() == VSPutNode::VT_2)
			{
				OutString +=VSRenderer::ms_pRenderer->Float2() + _T(" ");/*_T("float2 ");*/
				Temp = VSRenderer::ms_pRenderer->Float2Const(_T("0"),_T("0"));/*_T("float2(0,0)");*/
			}
			else if(m_pInput[Index[i]]->GetValueType() == VSPutNode::VT_3)
			{
				OutString +=VSRenderer::ms_pRenderer->Float3() + _T(" ");/*_T("float3 ");*/
				Temp = VSRenderer::ms_pRenderer->Float3Const(_T("0"),_T("0"),_T("0"));/*_T("float3(0,0,0)");*/
			}
			else if(m_pInput[Index[i]]->GetValueType() == VSPutNode::VT_4)
			{
				OutString +=VSRenderer::ms_pRenderer->Float4() + _T(" ");/*_T("float4 ");*/
				Temp = VSRenderer::ms_pRenderer->Float4Const(_T("0"),_T("0"),_T("0"),_T("1"));/*_T("float4(0,0,0,1)");*/
			}
			else
				return 0;
			if(!m_pInput[Index[i]]->GetOutputLink())
			{
				OutString += m_pInput[Index[i]]->GetNodeName().GetString() + _T(" = ") + Temp + _T(";\n");
				continue;
			}
			// 		if(m_pInput[i]->GetValueType() != m_pInput[i]->GetOutputLink()->GetValueType())
			// 			return 0;
			OutString += GetValueEqualString(m_pInput[Index[i]]->GetOutputLink(),m_pInput[Index[i]]);/*m_pInput[i]->GetNodeName() + _T(" = ") + m_pInput[i]->GetOutputLink()->GetNodeName() + _T(";\n");*/
		}
		
	}
	return 1;
}